<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------

// OneThink常量定义
const ONETHINK_VERSION    = '1.0.131218';
const ONETHINK_ADDON_PATH = './Addons/';

/**
 * 系统公共库文件
 * 主要定义系统公共函数库
 */

/**
 * 检测用户是否登录
 * @return integer 0-未登录，大于0-当前登录用户ID
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_login(){
    $user = session('user_auth');
    if (empty($user)) {
        return 0;
    } else {
        return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
    }
}
/**
 * 消费记录
 * type 类型,1 充值，2 提现，3购买，4,卖出商品，5 ,分销提成 6,退款 7 赠送播豆 8 播豆转账,10，卖商品送播豆
 * type 类型 11 观看直播 12 下载直播 13 打赏 14 视频收取费用 15 推荐
 * pur_type 1人民币 2播豆
 */
function payrecord($uid,$order_id,$money,$type,$pur_type=1){
    $data = [];
    $data['uid']       = $uid;
    $data['order_id'] = $order_id;
    $data['type']   = $type;
    $data['status'] = 1;
    $data['money']  = $money;
    $data['pur_type']  = $pur_type;
    $data['month']  = date('Ym', time());
    $data['createtime'] = time();
    $res5 = M('user_trade')->add($data);
}

/**
 * 检测当前用户是否为管理员
 * @return boolean true-管理员，false-非管理员
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_administrator($uid = null){
    $uid = is_null($uid) ? is_login() : $uid;
    return $uid && (intval($uid) === C('USER_ADMINISTRATOR'));
}

/**
 * 字符串转换为数组，主要用于把分隔符调整到第二个参数
 * @param  string $str  要分割的字符串
 * @param  string $glue 分割符
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function str2arr($str, $glue = ','){
    $arr = explode($glue, $str);
    is_array($arr) || $arr = array($arr); 
    return $arr;
}

/**
 * 数组转换为字符串，主要用于把分隔符调整到第二个参数
 * @param  array  $arr  要连接的数组
 * @param  string $glue 分割符
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function arr2str($arr, $glue = ','){
    return implode($glue, $arr);
}

/**
 * 字符串截取，支持中文和其他编码
 * @static
 * @access public
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string
 */
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif(function_exists('iconv_substr')) {
        $slice = iconv_substr($str,$start,$length,$charset);
        if(false === $slice) {
            $slice = '';
        }
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice.'...' : $slice;
}

/**
 * 系统加密方法
 * @param string $data 要加密的字符串
 * @param string $key  加密密钥
 * @param int $expire  过期时间 单位 秒
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_encrypt($data, $key = '', $expire = 0) {
    $key  = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = base64_encode($data);
    $x    = 0;
    $len  = strlen($data);
    $l    = strlen($key);
    $char = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    $str = sprintf('%010d', $expire ? $expire + time():0);

    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1)))%256);
    }
    return str_replace(array('+','/','='),array('-','_',''),base64_encode($str));
}

/**
 * 系统解密方法
 * @param  string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param  string $key  加密密钥
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_decrypt($data, $key = ''){
    $key    = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data   = str_replace(array('-','_'),array('+','/'),$data);
    $mod4   = strlen($data) % 4;
    if ($mod4) {
       $data .= substr('====', $mod4);
    }
    $data   = base64_decode($data);
    $expire = substr($data,0,10);
    $data   = substr($data,10);

    if($expire > 0 && $expire < time()) {
        return '';
    }
    $x      = 0;
    $len    = strlen($data);
    $l      = strlen($key);
    $char   = $str = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l) $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1))<ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }else{
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return base64_decode($str);
}

/**
 * 数据签名认证
 * @param  array  $data 被认证的数据
 * @return string       签名
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function data_auth_sign($data) {
    //数据类型检测
    if(!is_array($data)){
        $data = (array)$data;
    }
    ksort($data); //排序
    $code = http_build_query($data); //url编码并生成query字符串
    $sign = sha1($code); //生成签名
    return $sign;
}

/**
* 对查询结果集进行排序
* @access public
* @param array $list 查询结果
* @param string $field 排序的字段名
* @param array $sortby 排序类型
* asc正向排序 desc逆向排序 nat自然排序
* @return array
*/
function list_sort_by($list,$field, $sortby='asc') {
   if(is_array($list)){
       $refer = $resultSet = array();
       foreach ($list as $i => $data)
           $refer[$i] = &$data[$field];
       switch ($sortby) {
           case 'asc': // 正向排序
                asort($refer);
                break;
           case 'desc':// 逆向排序
                arsort($refer);
                break;
           case 'nat': // 自然排序
                natcasesort($refer);
                break;
       }
       foreach ( $refer as $key=> $val)
           $resultSet[] = &$list[$key];
       return $resultSet;
   }
   return false;
}

/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function list_to_tree($list, $pk='id', $pid = 'pid', $child = '_child', $root = 0) {
    // 创建Tree
    $tree = array();
    if(is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] =& $list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId =  $data[$pid];
            if ($root == $parentId) {
                $tree[] =& $list[$key];
            }else{
                if (isset($refer[$parentId])) {
                    $parent =& $refer[$parentId];
                    $parent[$child][] =& $list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * 将list_to_tree的树还原成列表
 * @param  array $tree  原来的树
 * @param  string $child 孩子节点的键
 * @param  string $order 排序显示的键，一般是主键 升序排列
 * @param  array  $list  过渡用的中间数组，
 * @return array        返回排过序的列表数组
 * @author yangweijie <yangweijiester@gmail.com>
 */
function tree_to_list($tree, $child = '_child', $order='id', &$list = array()){
    if(is_array($tree)) {
        $refer = array();
        foreach ($tree as $key => $value) {
            $reffer = $value;
            if(isset($reffer[$child])){
                unset($reffer[$child]);
                tree_to_list($value[$child], $child, $order, $list);
            }
            $list[] = $reffer;
        }
        $list = list_sort_by($list, $order, $sortby='asc');
    }
    return $list;
}

/**
 * 格式化字节大小
 * @param  number $size      字节数
 * @param  string $delimiter 数字和单位分隔符
 * @return string            格式化后的带单位的大小
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function format_bytes($size, $delimiter = '') {
    $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 设置跳转页面URL
 * 使用函数再次封装，方便以后选择不同的存储方式（目前使用cookie存储）
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function set_redirect_url($url){
    cookie('redirect_url', $url);
}

/**
 * 获取跳转页面URL
 * @return string 跳转页URL
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function get_redirect_url(){
    $url = cookie('redirect_url');
    return empty($url) ? __APP__ : $url;
}

/**
 * 处理插件钩子
 * @param string $hook   钩子名称
 * @param mixed $params 传入参数
 * @return void
 */
function hook($hook,$params=array()){
    \Think\Hook::listen($hook,$params);
}

/**
 * 获取插件类的类名
 * @param strng $name 插件名
 */
function get_addon_class($name){
    $class = "Addons\\{$name}\\{$name}Addon";
    return $class;
}

/**
 * 获取插件类的配置文件数组
 * @param string $name 插件名
 */
function get_addon_config($name){
    $class = get_addon_class($name);
    if(class_exists($class)) {
        $addon = new $class();
        return $addon->getConfig();
    }else {
        return array();
    }
}

/**
 * 插件显示内容里生成访问插件的url
 * @param string $url url
 * @param array $param 参数
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function addons_url($url, $param = array()){
    $url        = parse_url($url);
    $case       = C('URL_CASE_INSENSITIVE');
    $addons     = $case ? parse_name($url['scheme']) : $url['scheme'];
    $controller = $case ? parse_name($url['host']) : $url['host'];
    $action     = trim($case ? strtolower($url['path']) : $url['path'], '/');

    /* 解析URL带的参数 */
    if(isset($url['query'])){
        parse_str($url['query'], $query);
        $param = array_merge($query, $param);
    }

    /* 基础参数 */
    $params = array(
        '_addons'     => $addons,
        '_controller' => $controller,
        '_action'     => $action,
    );
    $params = array_merge($params, $param); //添加额外参数

    return U('Addons/execute', $params);
}

/**
 * 时间戳格式化
 * @param int $time
 * @return string 完整的时间显示
 * @author huajie <banhuajie@163.com>
 */
function time_format($time = NULL,$format='Y-m-d H:i'){
    $time = $time === NULL ? NOW_TIME : intval($time);
    return date($format, $time);
}
/**
 * 用户头像
 * @parm int $uid
 */
function get_avatar($uid = 0){
    static $list;
    /* 获取缓存数据 */
    if(empty($list)){
        $list = S('sys_active_avatar_user_list',null);
    }
    /* 查找用户信息 */
    $key = "u{$uid}";
    if(isset($list[$key])){ //已缓存，直接使用
        $avatar_path = $list[$key];
    } else { //调用接口获取用户信息
        $info = M('Member')->field('avatar')->find($uid);
        if($info !== false && $info['avatar'] ){            
            $avatar_path = $list[$key] = get_url($info['avatar']);
            /* 缓存用户 */
            $count = count($list);
            $max   = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            // S('sys_active_avatar_user_list', $list);
        } else {
            $avatar_path = '';
        }
    }
    return $avatar_path;

}

/**
 * 根据用户ID获取用户名
 * @param  integer $uid 用户ID
 * @return string       用户名
 */
function get_username($uid = 0){
    $User = new User\Api\UserApi();
    $info = $User->info($uid);
    if($info && isset($info[1])){
        $name = $info[1];
    } else {
        $name = '';
    }
    return $name;
}

/**
 * 根据用户ID获取用户昵称
 * @param  integer $uid 用户ID
 * @return string       用户昵称
 */
function get_nickname($uid = 0){
    static $list;
    /* if(!($uid && is_numeric($uid))){ //获取当前登录用户名
        return session('user_auth.username');
    } */

    /* 获取缓存数据 */
    if(empty($list)){
        $list = S('sys_user_nickname_list');
    }

    /* 查找用户信息 */
    $key = "u{$uid}";
    if(isset($list[$key])){ //已缓存，直接使用
        $name = $list[$key];
    } else { //调用接口获取用户信息
        $info = M('Member')->field('nickname')->find($uid);
        if($info !== false && $info['nickname'] ){
            $nickname = $info['nickname'];
            $name = $list[$key] = $nickname;
            /* 缓存用户 */
            $count = count($list);
            $max   = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            S('sys_user_nickname_list', $list);
        } else {
            $name = '';
        }
    }
    return $name;
}



/**
 * 获取文档模型信息
 * @param  integer $id    模型ID
 * @param  string  $field 模型字段
 * @return array
 */
function get_document_model($id = null, $field = null){
    static $list;

    /* 非法分类ID */
    if(!(is_numeric($id) || is_null($id))){
        return '';
    }

    /* 读取缓存数据 */
    if(empty($list)){
        $list = S('DOCUMENT_MODEL_LIST');
    }

    /* 获取模型名称 */
    if(empty($list)){
        $map   = array('status' => 1, 'extend' => 1);
        $model = M('Model')->where($map)->field(true)->select();
        foreach ($model as $value) {
            $list[$value['id']] = $value;
        }
        S('DOCUMENT_MODEL_LIST', $list); //更新缓存
    }

    /* 根据条件返回数据 */
    if(is_null($id)){
        return $list;
    } elseif(is_null($field)){
        return $list[$id];
    } else {
        return $list[$id][$field];
    }
}

/**
 * 解析UBB数据
 * @param string $data UBB字符串
 * @return string 解析为HTML的数据
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function ubb($data){
    //TODO: 待完善，目前返回原始数据
    return $data;
}

/**
 * 记录行为日志，并执行该行为的规则
 * @param string $action 行为标识
 * @param string $model 触发行为的模型名
 * @param int $record_id 触发行为的记录id
 * @param int $user_id 执行行为的用户id
 * @return boolean
 * @author huajie <banhuajie@163.com>
 */
function action_log($action = null, $model = null, $record_id = null, $user_id = null){

    //参数检查
    if(empty($action) || empty($model) || empty($record_id)){
        return '参数不能为空';
    }
    if(empty($user_id)){
        $user_id = is_login();
    }

    //查询行为,判断是否执行
    $action_info = M('Action')->getByName($action);
    if($action_info['status'] != 1){
        return '该行为被禁用或删除';
    }

    //插入行为日志
    $data['action_id']      =   $action_info['id'];
    $data['user_id']        =   $user_id;
    $data['action_ip']      =   ip2long(get_client_ip());
    $data['model']          =   $model;
    $data['record_id']      =   $record_id;
    $data['create_time']    =   NOW_TIME;

    //解析日志规则,生成日志备注
    if(!empty($action_info['log'])){
        if(preg_match_all('/\[(\S+?)\]/', $action_info['log'], $match)){
            $log['user']    =   $user_id;
            $log['record']  =   $record_id;
            $log['model']   =   $model;
            $log['time']    =   NOW_TIME;
            $log['data']    =   array('user'=>$user_id,'model'=>$model,'record'=>$record_id,'time'=>NOW_TIME);
            foreach ($match[1] as $value){
                $param = explode('|', $value);
                if(isset($param[1])){
                    $replace[] = call_user_func($param[1],$log[$param[0]]);
                }else{
                    $replace[] = $log[$param[0]];
                }
            }
            $data['remark'] =   str_replace($match[0], $replace, $action_info['log']);
        }else{
            $data['remark'] =   $action_info['log'];
        }
    }else{
        //未定义日志规则，记录操作url
        $data['remark']     =   '操作url：'.$_SERVER['REQUEST_URI'];
    }

    M('ActionLog')->add($data);

    if(!empty($action_info['rule'])){
        //解析行为
        $rules = parse_action($action, $user_id);

        //执行行为
        $res = execute_action($rules, $action_info['id'], $user_id);
    }
}

/**
 * 解析行为规则
 * 规则定义  table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
 * 规则字段解释：table->要操作的数据表，不需要加表前缀；
 *              field->要操作的字段；
 *              condition->操作的条件，目前支持字符串，默认变量{$self}为执行行为的用户
 *              rule->对字段进行的具体操作，目前支持四则混合运算，如：1+score*2/2-3
 *              cycle->执行周期，单位（小时），表示$cycle小时内最多执行$max次
 *              max->单个周期内的最大执行次数（$cycle和$max必须同时定义，否则无效）
 * 单个行为后可加 ； 连接其他规则
 * @param string $action 行为id或者name
 * @param int $self 替换规则里的变量为执行用户的id
 * @return boolean|array: false解析出错 ， 成功返回规则数组
 * @author huajie <banhuajie@163.com>
 */
function parse_action($action = null, $self){
    if(empty($action)){
        return false;
    }

    //参数支持id或者name
    if(is_numeric($action)){
        $map = array('id'=>$action);
    }else{
        $map = array('name'=>$action);
    }

    //查询行为信息
    $info = M('Action')->where($map)->find();
    if(!$info || $info['status'] != 1){
        return false;
    }

    //解析规则:table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
    $rules = $info['rule'];
    $rules = str_replace('{$self}', $self, $rules);
    $rules = explode(';', $rules);
    $return = array();
    foreach ($rules as $key=>&$rule){
        $rule = explode('|', $rule);
        foreach ($rule as $k=>$fields){
            $field = empty($fields) ? array() : explode(':', $fields);
            if(!empty($field)){
                $return[$key][$field[0]] = $field[1];
            }
        }
        //cycle(检查周期)和max(周期内最大执行次数)必须同时存在，否则去掉这两个条件
        if(!array_key_exists('cycle', $return[$key]) || !array_key_exists('max', $return[$key])){
            unset($return[$key]['cycle'],$return[$key]['max']);
        }
    }

    return $return;
}

/**
 * 执行行为
 * @param array $rules 解析后的规则数组
 * @param int $action_id 行为id
 * @param array $user_id 执行的用户id
 * @return boolean false 失败 ， true 成功
 * @author huajie <banhuajie@163.com>
 */
function execute_action($rules = false, $action_id = null, $user_id = null){
    if(!$rules || empty($action_id) || empty($user_id)){
        return false;
    }

    $return = true;
    foreach ($rules as $rule){

        //检查执行周期
        $map = array('action_id'=>$action_id, 'user_id'=>$user_id);
        $map['create_time'] = array('gt', NOW_TIME - intval($rule['cycle']) * 3600);
        $exec_count = M('ActionLog')->where($map)->count();
        if($exec_count > $rule['max']){
            continue;
        }

        //执行数据库操作
        $Model = M(ucfirst($rule['table']));
        $field = $rule['field'];
        $res = $Model->where($rule['condition'])->setField($field, array('exp', $rule['rule']));

        if(!$res){
            $return = false;
        }
    }
    return $return;
}

//基于数组创建目录和文件
function create_dir_or_files($files){
    foreach ($files as $key => $value) {
        if(substr($value, -1) == '/'){
            mkdir($value);
        }else{
            @file_put_contents($value, '');
        }
    }
}

if(!function_exists('array_column')){
    function array_column(array $input, $columnKey, $indexKey = null) {
        $result = array();
        if (null === $indexKey) {
            if (null === $columnKey) {
                $result = array_values($input);
            } else {
                foreach ($input as $row) {
                    $result[] = $row[$columnKey];
                }
            }
        } else {
            if (null === $columnKey) {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row;
                }
            } else {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row[$columnKey];
                }
            }
        }
        return $result;
    }
}

/**
 * 获取表名（不含表前缀）
 * @param string $model_id
 * @return string 表名
 * @author huajie <banhuajie@163.com>
 */
function get_table_name($model_id = null){
    if(empty($model_id)){
        return false;
    }
    $Model = M('Model');
    $name = '';
    $info = $Model->getById($model_id);
    if($info['extend'] != 0){
        $name = $Model->getFieldById($info['extend'], 'name').'_';
    }
    $name .= $info['name'];
    return $name;
}

/**
 * 获取属性信息并缓存
 * @param  integer $id    属性ID
 * @param  string  $field 要获取的字段名
 * @return string         属性信息
 */
function get_model_attribute($model_id, $group = true){
    static $list;

    /* 非法ID */
    if(empty($model_id) || !is_numeric($model_id)){
        return '';
    }

    /* 读取缓存数据 */
    if(empty($list)){
        $list = S('attribute_list');
    }

    /* 获取属性 */
    if(!isset($list[$model_id])){
        $map = array('model_id'=>$model_id);
        $extend = M('Model')->getFieldById($model_id,'extend');

        if($extend){
            $map = array('model_id'=> array("in", array($model_id, $extend)));
        }
        $info = M('Attribute')->where($map)->select();
        $list[$model_id] = $info;
        //S('attribute_list', $list); //更新缓存
    }

    $attr = array();
    foreach ($list[$model_id] as $value) {
        $attr[$value['id']] = $value;
    }

    if($group){
        $sort  = M('Model')->getFieldById($model_id,'field_sort');

        if(empty($sort)){	//未排序
            $group = array(1=>array_merge($attr));
        }else{
            $group = json_decode($sort, true);

            $keys  = array_keys($group);
            foreach ($group as &$value) {
                foreach ($value as $key => $val) {
                    $value[$key] = $attr[$val];
                    unset($attr[$val]);
                }
            }

            if(!empty($attr)){
                $group[$keys[0]] = array_merge($group[$keys[0]], $attr);
            }
        }
        $attr = $group;
    }
    return $attr;
}

/**
 * 调用系统的API接口方法（静态方法）
 * api('User/getName','id=5'); 调用公共模块的User接口的getName方法
 * api('Admin/User/getName','id=5');  调用Admin模块的User接口
 * @param  string  $name 格式 [模块名]/接口名/方法名
 * @param  array|string  $vars 参数
 */
function api($name,$vars=array()){
    $array     = explode('/',$name);
    $method    = array_pop($array);
    $classname = array_pop($array);
    $module    = $array? array_pop($array) : 'Common';
    $callback  = $module.'\\Api\\'.$classname.'Api::'.$method;
    if(is_string($vars)) {
        parse_str($vars,$vars);
    }
    return call_user_func_array($callback,$vars);
}

/**
 * 根据条件字段获取指定表的数据
 * @param mixed $value 条件，可用常量或者数组
 * @param string $condition 条件字段
 * @param string $field 需要返回的字段，不传则返回整个数据
 * @param string $table 需要查询的表
 * @author huajie <banhuajie@163.com>
 */
function get_table_field($value = null, $condition = 'id', $field = null, $table = null){
    if(empty($value) || empty($table)){
        return false;
    }

    //拼接参数
    $map[$condition] = $value;
    $info = M(ucfirst($table))->where($map);
    if(empty($field)){
        $info = $info->field(true)->find();
    }else{
        $info = $info->getField($field);
    }
    return $info;
}

/**
 * 获取链接信息
 * @param int $link_id
 * @param string $field
 * @return 完整的链接信息或者某一字段
 * @author huajie <banhuajie@163.com>
 */
function get_link($link_id = null, $field = 'url'){
    $link = '';
    if(empty($link_id)){
        return $link;
    }
    $link = M('Url')->getById($link_id);
    if(empty($field)){
        return $link;
    }else{
        return $link[$field];
    }
}

/**
 * 获取文档封面图片
 * @param int $cover_id
 * @param string $field
 * @return 完整的数据  或者  指定的$field字段值
 * @author huajie <banhuajie@163.com>
 */
function get_cover($cover_id, $field = null){
    if(empty($cover_id)){
        return false;
    }
    $picture = M('Picture')->where(array('status'=>1))->getById($cover_id);
    return empty($field) ? $picture : $picture[$field];
}

/**
 * 获取视频文件
 * @param int $movie_id
 * @param string $field
 * @return 完整的数据  或者  指定的$field字段值
 * @author Ringo Chan <334258471@qq.com>
 */
function get_movie($movie_id, $field = null){
    if(empty($movie_id)){
        return false;
    }
    $movie = M('Movie')->where(array('status'=>1))->getById($movie_id);
    return empty($field) ? $movie : $movie[$field];
}

/**
 * 检查$pos(推荐位的值)是否包含指定推荐位$contain
 * @param number $pos 推荐位的值
 * @param number $contain 指定推荐位
 * @return boolean true 包含 ， false 不包含
 * @author huajie <banhuajie@163.com>
 */
function check_document_position($pos = 0, $contain = 0){
    if(empty($pos) || empty($contain)){
        return false;
    }

    //将两个参数进行按位与运算，不为0则表示$contain属于$pos
    $res = $pos & $contain;
    if($res !== 0){
        return true;
    }else{
        return false;
    }
}

/**
 * 获取数据的所有子孙数据的id值
 * @author 朱亚杰 <xcoolcc@gmail.com>
 */

function get_stemma($pids,Model &$model, $field='id'){
    $collection = array();

    //非空判断
    if(empty($pids)){
        return $collection;
    }

    if( is_array($pids) ){
        $pids = trim(implode(',',$pids),',');
    }
    $result     = $model->field($field)->where(array('pid'=>array('IN',(string)$pids)))->select();
    $child_ids  = array_column ((array)$result,'id');

    while( !empty($child_ids) ){
        $collection = array_merge($collection,$result);
        $result     = $model->field($field)->where( array( 'pid'=>array( 'IN', $child_ids ) ) )->select();
        $child_ids  = array_column((array)$result,'id');
    }
    return $collection;
}

/**
 * 邮件发送函数
 * @author Ringo Chan <334258471@qq.com>
 */
function sendMail($to, $subject, $content) {
    vendor('phpmailer.class#phpmailer');
    $mail = new PHPMailer(); //实例化
    $mail->IsSMTP(); // 启用SMTP
    $mail->Host = C('SMTP_HOST'); //SMTP服务器 这里以新浪邮箱为例子
    $mail->Port = C('SMTP_PORT');  //邮件发送端口
    $mail->SMTPAuth   = true;  //启用SMTP认证
    $mail->CharSet  = "UTF-8"; //字符集
    $mail->Encoding = "base64"; //编码方式
    $mail->Username = C('SMTP_USER');  //你的邮箱
    $mail->Password = C('SMTP_PASS');  //你的密码
    $mail->Subject = $subject; //邮件标题
    $mail->From = C('SMTP_USER');  //发件人地址（也就是你的邮箱）
    $mail->FromName = C('EMAIL_FROM');  //发件人姓名
    $mail->AddAddress($to);//添加收件人地址，昵称
    //$mail->AddAttachment("test,zip","重命名附件.zip"); // 添加附件,并重命名
    $mail->IsHTML(true); //支持html格式内容
    $mail->Body = $content; //邮件内容
    //发送
    if(!$mail->Send()) {
        return false;
    } else {
        return true;
    }
}

/**
 * 获取省份列表
 * 
 * @author Ringo Chan <334258471@qq.com>
 */
function getProvinces(){
    $list = S('CACHE_ADDRESS_PROVINCE');
    
    if (empty($list)) {
        $M_hat_province = M('hat_province');
        
        $list = $M_hat_province->select();
        
        S('CACHE_ADDRESS_PROVINCE', $list);
    }
    
    return $list;
}

/**
 * 获取城市列表
 *
 * @param string province_id 地区代码
 * @author Ringo Chan <334258471@qq.com>
 */
function getCities($province_id){
    $list = S('CACHE_ADDRESS_CITY_'.$province_id);

    if (empty($list)) {
        $M_hat_city = M('hat_city');

        $list = $M_hat_city->where(array('father'=>$province_id))->select();

        S('CACHE_ADDRESS_CITY_'.$province_id, $list);
    }

    return $list;
}

/**
 * 获取所有区县
 *
 * @param string city_id 地区代码
 * @author Ringo Chan <334258471@qq.com>
 */
function getAreas($city_id){
    $list = S('CACHE_ADDRESS_AREA_'.$city_id);

    if (empty($list)) {
        $M_hat_area = M('hat_area');

        $list = $M_hat_area->where(array('father'=>$city_id))->select();

        S('CACHE_ADDRESS_AREA_'.$city_id, $list);
    }

    return $list;
}

/**
 * 获取状态信息
 * 
 * @param string model 模块
 * @author Ringo Chan <334258471@qq.com>
 */
function getStatus($model, $id = NULL){
    $status = array();
    
    switch (strtolower($model)) {
        case 'product':
            $status = array(-9=>'违规商品', 0=>'未上架', 1=>'出售中');
            break;
        case 'security_7days':
            $status = array(0=>'无',1=>'支持7天无理由退货');
            break;
        case 'security_delivery':
            $status = array(0=>'无',1=>'24小时',2=>'48小时',3=>'72小时');
            break;
        case 'discount':
            $status = array(1=>'9折',2=>'8折',3=>'7折',4=>'6折',5=>'5折',6=>'4折',7=>'3折',8=>'2折',9=>'1折');
            break;
        case 'hours':
            $status = array(0=>'00:00',1=>'01:00',2=>'02:00',3=>'03:00',4=>'04:00',5=>'05:00',6=>'06:00',7=>'07:00',8=>'08:00',9=>'09:00',10=>'10:00',11=>'11:00',12=>'12:00',13=>'13:00',14=>'14:00',15=>'15:00',16=>'16:00',17=>'17:00',18=>'18:00',19=>'19:00',20=>'20:00',21=>'21:00',22=>'22:00',23=>'23:00');
            break;
        case 'paizhao':
            $status = array(0=>'已生效',1=>'未生效');
            break;
        case 'order':
            $status = array(0=>'未提交',1=>'已提交');
            break;
        case 'short_order':
            $status = array(0=>'未提交',1=>'已提交');
            break;
        case 'buyer_order':
            $status = array(0=>'未提交',1=>'已提交');
            break;
        case 'seller_order':
            $status = array(0=>'未提交',1=>'已提交');
            break;
        case 'payment':
            $status = array(0=>'充值中',1=>'充值成功',2=>'充值失败',3=>'过期订单');
            break;
        case 'return_status':
            $status = array(0=>'未确定',1=>'正在退款',2=>'已完成',3=>'已经取消',4=>'已拒绝');
            break;
        case 'checkup_status':
            $status = array(0=>'待付款',1=>'待发出',2=>'聚真宝待收货',3=>'正在鉴定',4=>'待收货',5=>'已完成',6=>'已取消');
            break;
        case 'bill_status':
            $status = array(0=>'失败',1=>'成功',2=>'取消');
            break;
        case 'rate_text':
            $status = array(1=>'好评',2=>'中评',3=>'差评');
            break;
        default:
            $status = array(0=>'否',1=>'是');
            break;
    }
    
    return is_null($id) ? $status : (isset($status[$id]) ? $status[$id] : NULL);
}

/**
 * 获取抢购会时间表
 *
 * @author Ringo Chan <334258471@qq.com>
 */
function getSpecialPanic(){
    $M_special_panic = M('special_panic');
    $list = $M_special_panic->where('status=1')->select();
    return $list;
}

/**
 * 获取选礼物分类
 * 
 * @author Ringo Chan <334258471@qq.com>
 */
function getSpecialGift($product_id = 0){
    $M_special_gift = M('special_gift');
    
    $list = $M_special_gift->where(array('start_time'=>array('egt', NOW_TIME), 'status'=>1))->select();
    
    if ($product_id > 0) {
        $M_product_special_gift = M('product_special_gift');
        
        $results = $M_product_special_gift->where(array('product_id'=>$product_id))->select();
        
        foreach ($list as $key => $item) {
            $status = false;
            
            foreach ($results as $result) {
                if ($result['special_gift_id']  == $item['id']) {
                    $status = true;
                }
            }
            
            $status ? $list[$key]['checked'] = 1 : $list[$key]['checked'] = 0;
        }
    }
    
    return $list;
}

/**
 * 校验日期格式是否正确
 *
 * @param string $date 日期
 * @param string $formats 需要检验的格式数组
 * @return boolean
 */
function checkDateIsValid($date, $formats = array("Y-m-d", "Y/m/d")) {
    $unixTime = strtotime($date);
    if (!$unixTime) { //strtotime转换不对，日期格式显然不对。
        return false;
    }
    //校验日期的有效性，只要满足其中一个格式就OK
    foreach ($formats as $format) {
        if (date($format, $unixTime) == $date) {
            return true;
        }
    }

    return false;
}

/**
 * 查看物流
 * 
 * @param string number 快递单号
 * @return array json
 */
function getExpress($com, $number){
    $list = array();
    
    if (empty($com) || empty($number)){
        return false;
    }
    
    /* if(empty($list)){
        $list = S('ORDER_SHIPPING_LIST');
    } */
    
    $M_shipping_api = M('shipping_api');
    $info = $M_shipping_api->where(array('in_used'=>1))->find();
    if (!$info){ return false; }
    $class = $info['code'];
    
    $key = "shipping{$class}{$com}{$number}";
    if(isset($list[$key]) && $list[$key]['cache'] >= NOW_TIME){ //已缓存，直接使用
        $list = $list[$key]['data'];
    } else {
        vendor('shipping.'.$class);
        $express = new $class();
        $feedback = $express->getorder($com, $number);
        $time = NOW_TIME + (60*60);
        $list[$key] = array('cache'=>$time, 'data'=>$feedback);
        S('ORDER_SHIPPING_LIST', $list);
        $list = $list[$key]['data'];
    }
    
    return $list;
}

/**
 * 获取订单产品列表
 * 
 * @param string orderno 订单号/订单编号
 * @return array json
 */
function getOrderProducts($orderno){
    $M_order = M('order');
    $M_order_product = M('order_product');
    
    $order_info = $M_order->where(array('id|order_no'=>$orderno))->find();
    
    if(!$order_info) {return false;}
    
    $list = $M_order_product->where(array('order_id'=>$order_info['id']))->select();
    
    return $list; 
}

/**
 * 获取物流公司
 * 
 * @reutrn array
 */
function getShippings(){
    static $list = array();
    
    if (empty($list)) {
        $list = S('CACHE_SHIPPING_LIST');
    }
    
    if (empty($list)) {
        $M_shipping = M('shipping');
        
        $list = $M_shipping->field(array('code', 'title', 'website', 'mobile', 'price'))->order('sort ASC')->select();
        
        S('CACHE_SHIPPING_LIST', $list);
    }
    
    return $list;
}

// $count为总条目数，$page为当前页码，$page_size为每页显示条目数<br />
function show_page($count, $page, $page_size, $u_param, $extend_array =null)
{
    $page_count = ceil($count / $page_size); // 计算得出总页数

    $init = 1;
    $page_len = 7;
    $max_p = $page_count;
    $pages = $page_count;

    // 判断当前页码
    $page = (empty($page) || $page < 0) ? 1 : $page;

    // 分页功能代码
    $page_len = ($page_len % 2) ? $page_len : $page_len + 1; // 页码个数
    $pageoffset = ($page_len - 1) / 2; // 页码个数左右偏移量

    $navs = '';

    if ($pages != 0) {
        if ($page != 1) {
            $navs .= "<a class='a1' href=\"" . page_url(1, $u_param, $extend_array) . "\">首页</a> "; // 第一页
            $navs .= "<a class='a1' href=\"" . page_url($page - 1, $u_param, $extend_array) . "\">上页</a>"; // 上一页
        } else {
            $navs .= "<a class='disabled'>首页</a>";
            $navs .= "<a class='disabled'>上页</a>";
        }
        if ($pages > $page_len) {
            // 如果当前页小于等于左偏移
            if ($page <= $pageoffset) {
                $init = 1;
                $max_p = $page_len;
            } else // 如果当前页大于左偏移
            {
                // 如果当前页码右偏移超出最大分页数
                if ($page + $pageoffset >= $pages + 1) {
                    $init = $pages - $page_len + 1;
                } else {
                    // 左右偏移都存在时的计算
                    $init = $page - $pageoffset;
                    $max_p = $page + $pageoffset;
                }
            }
        }
        for ($i = $init; $i <= $max_p; $i ++) {
            if ($i == $page) {
                $navs .= "<span >" . $i . '</span>';
            } else {
                $navs .= " <a href=\"" . page_url($i, $u_param, $extend_array) . "\">" . $i . "</a>";
            }
        }
        if ($page != $pages) {
            $navs .= " <a href=\"" . page_url($page + 1, $u_param, $extend_array) . "\" class='a1'>下页</a> "; // 下一页
            $navs .= "<a href=\"" . page_url($page, $u_param, $extend_array) . "\" class='a1'>末页</a>"; // 最后一页
        } else {
            $navs .= "<a class='a1'>下页</a>";
            $navs .= "<a class='a1'>末页</a>";
        }
        return $navs;
    }
}

/*
 * 连接二维数组
 */
function arr2tostr($arr)
{
    foreach ($arr as $v) {
        $v = join(",", $v); // 降维,也可以用implode,将一维数组转换为用逗号连接的字符串
        $temp[] = $v;
    }
    $t = "";
    foreach ($temp as $v) {
        $t .= $v . ",";
    }
    $t = substr($t, 0, - 1);
    return $t;
}
/**
 * 生成号
 */
function build_no(){
    /* 选择一个随机的方案 */
    mt_srand((double) microtime() * 1000000);
     
    return date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
}

/**
 * 字符替换
 */
function substr_cut($user_name){
    $strlen     = mb_strlen($user_name, 'utf-8');
    $firstStr     = mb_substr($user_name, 0, 1, 'utf-8');
    $lastStr     = mb_substr($user_name, -2, 2, 'utf-8');
    return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($user_name, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 3) . $lastStr;
}

/**
 * 添加消息
 * @param int $type 消息类型 1物流 2交易 3 通知  4定时 5活动
 * @param string $title 消息标题
 */
function addMessage($type,$title,$msg,$to_uid,$send_uid,$cover_id=''){
    $M_mesage=M('message');
    $data=array();
    $data['type']=$type;
    $data['title']=$title;
    $data['message']=$msg;
    $data['create_time']=NOW_TIME;
    $data['to_uid']=$to_uid;
    $data['send_uid']=$send_uid;
    $data['cover_id']=$cover_id;    
    
    $M_mesage->add($data);
}

/**
 * 国家列表
 */
function getCountries($var) {
    $arrs = array(
        0 => '国内',
        1 => '国际'
    );
    if ($var == null) {
        return $arrs;
    } else {
        return isset($arrs[$var]) ? $arrs[$var] : null;
    }
}

/**
 * 礼品列表
 */
function getGifts($var) {
    $arrs = array(
        1 => '掌声',
        2 => '小拇指'
    );
    if ($var == null) {
        return $arrs;
    } else {
        return isset($arrs[$var]) ? $arrs[$var] : null;
    }
}

/**
 * 广告位置列表
 */
function getAdPositions($var) {
    $arrs = array(
        'index_banner' => '首页轮播',
        'index_recom' => '首页推荐',
        'snatch_banner' => '人品大爆发轮播',
        'category_header' => '分类列表头部',
        'category_recom' => '分类列表推荐',
        'panic_banner' => '抢购会轮播',
        'free_banner' => '需求轮播',
        'score_show_img' => '首页播豆商品图片'
    );
    if ($var == null) {
        return $arrs;
    } else {
        return isset($arrs[$var]) ? $arrs[$var] : null;
    }
}

function getAdAdminPositions($var) {
    $arrs = array(
        'index_recom' => '首页推荐',
        'category_recom' => '分类列表推荐',
        // 'panic_banner' => '抢购会轮播',
        'free_banner' => '需求轮播',
        // 'score_show_img' => '首页积分商品图片'
    );
    if ($var == null) {
        return $arrs;
    } else {
        return isset($arrs[$var]) ? $arrs[$var] : null;
    }
}

/**
 * 广告位置列表
 */
function getGroups($var) {
    $arrs = array(
        'product' => '商品',
        'free' => '需求',
    );
    if ($var == null) {
        return $arrs;
    } else {
        return isset($arrs[$var]) ? $arrs[$var] : null;
    }
}

/**
 * 计算会员等级
 */
function calculation_level($signnum) {
    $level = 1;
    if ($signnum < 0) {
        return 0;
    } elseif ($signnum <= 2) {
        $level = $signnum;
        return $level;
    }
    $signlog = 2;
    for ($i = 3; $i <= 100; $i++) {
        $signlog = $signlog * 2;
        if ($signlog > $signnum) {
            $level = $i - 1;
            break;
        }
    }
    return $level;
}

function calculation_shop_level($zhangsheng, $xiaomuzhi) {
    $zhangsheng < 0 && $zhangsheng = 0;
    $xiaomuzhi < 0 && $xiaomuzhi = 0;
    $zhangsheng = intval($zhangsheng) - (10 * intval($xiaomuzhi));
    return calculation_level($zhangsheng);
}

/**
 * 百度开发者key
 */
function baiduKey()
{
    return C('BAIDU_MAP_AK');
}

/**
 * 获取IP
 */
function GetIp()
{
    $realip = '';
    $unknown = 'unknown';
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR']) && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($arr as $ip) {
                $ip = trim($ip);
                if ($ip != 'unknown') {
                    $realip = $ip;
                    break;
                }
            }
        } else
            if (isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP']) && strcasecmp($_SERVER['HTTP_CLIENT_IP'], $unknown)) {
                $realip = $_SERVER['HTTP_CLIENT_IP'];
            } else
                if (isset($_SERVER['REMOTE_ADDR']) && ! empty($_SERVER['REMOTE_ADDR']) && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)) {
                    $realip = $_SERVER['REMOTE_ADDR'];
                } else {
                    $realip = $unknown;
                }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), $unknown)) {
            $realip = getenv("HTTP_X_FORWARDED_FOR");
        } else
            if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), $unknown)) {
                $realip = getenv("HTTP_CLIENT_IP");
            } else
                if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), $unknown)) {
                    $realip = getenv("REMOTE_ADDR");
                } else {
                    $realip = $unknown;
                }
    }
    $realip = preg_match("/[\d\.]{7,15}/", $realip, $matches) ? $matches[0] : $unknown;
    return $realip;
}

/**
 * 获取位置坐标
 */
function getlocation()
{
    $ip = GetIp();
    $baidu_ak = baiduKey();
    $location = @file_get_contents('http://api.map.baidu.com/location/ip?ak=' . $baidu_ak . '&ip=' . $ip . '&coor=bd09ll');
    return $location;
}

/*
 * 根据ip获取城市
 */
function getCity()
{
    $location_array = json_decode(getlocation(), true);
    if (! is_array($location_array)) {
        return '其他';
    }

    $city = $location_array['content']['address_detail']['city'];
    return $city ? $city : null;
}

/**
 * 转换时间
 */
function transfer_time($time)
{
    //获取今天凌晨的时间戳
    $day = strtotime(date('Y-m-d',time()));
    //获取昨天凌晨的时间戳
    $pday = strtotime(date('Y-m-d',strtotime('-1 day')));
    //获取现在的时间戳
    $nowtime = time();
    $tc = $nowtime-$time;
    if($time<$pday){
        $str = date('Y-m-d H:i:s',$time);
    }elseif($time<$day && $time>$pday){
        $str = "昨天";
    }elseif($tc>60*60){
        $str = floor($tc/(60*60))."小时前";
    }elseif($tc>60){
        $str = floor($tc/60)."分钟前";
    }else{
        $str = "刚刚";
    }
    return $str;
}

/**
 * 日期时间友好显示
 * @param $time
 * @return bool|string
 */
function friend_date($time)
{
    if (!$time) {
        return false;
    }
    $fdate = '';
    $d = time() - intval($time);
    $ld = $time - mktime(0, 0, 0, 0, 0, date('Y')); //得出年
    $md = $time - mktime(0, 0, 0, date('m'), 0, date('Y')); //得出月
    $byd = $time - mktime(0, 0, 0, date('m'), date('d') - 2, date('Y')); //前天
    $yd = $time - mktime(0, 0, 0, date('m'), date('d') - 1, date('Y')); //昨天
    $dd = $time - mktime(0, 0, 0, date('m'), date('d'), date('Y')); //今天
    if ($d == 0) {
        $fdate = '刚刚';
    } else {
        switch ($d) {
            case $d < 60:
                $fdate = $d . '秒前';
                break;
            case $d < 3600:
                $fdate = floor($d / 60) . '分钟前';
                break;
            case $d < $dd:
                $fdate = floor($d / 3600) . '小时前';
                break;
            case $d < $yd:
                $fdate = '昨天' . date('H:i', $time);
                break;
            case $d < $byd:
                $fdate = '前天' . date('H:i', $time);
                break;
            case $d < $md:
                $fdate = date('m月d日 H:i', $time);
                break;
            case $d < $ld:
                $fdate = date('m月d日', $time);
                break;
            default:
                $fdate = date('Y年m月d日', $time);
                break;
        }
    }
    return $fdate;
}

/**
 * 生成二维码
 * @param $text
 * @param $fileName
 * @param float $size
 * @return string
 */
function qrcode($text,$fileName,$size=13.8){
    Vendor('Phpqrcode.phpqrcode');

    $path = './Uploads/qrcode/'.$fileName.'.png';

    QRcode::png($text,$path, $level = QR_ECLEVEL_L, $size, $margin = 4,
        $saveandprint=true, $back_color = 0xFFFFFF, $fore_color = 0x000000);

    return $path;
}

